package com.samehope.ar.util;

import com.alibaba.fastjson.JSON;
import org.springframework.http.HttpMethod;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @Description: http请求工具类(支持post RequestBody发送请求参数)
 * @Author: ZhangLuo
 * @Email: zhangluo@iworkgo.com
 */
public class HttpUtils {

    /**
     * 无参数, 无header的 Get请求
     * @param requestUrl
     * @return
     */
    public static String httpGet(String requestUrl) {
        return httpGet(requestUrl, null, null);
    }

    /**
     * 无header的 Get请求
     * @param requestUrl
     * @param params
     * @return
     */
    public static String httpGet(String requestUrl, Map<String, String> params) {
        return httpGet(requestUrl, params, null);
    }

    /**
     * http Get请求
     * @param requestUrl
     * @param params
     * @param headers
     * @return 响应结果的字符串
     */
    public static String httpGet(String requestUrl, Map<String, String> params, Map<String, String> headers) {

        try {
            URL url;
            // 处理请求参数
            StringBuilder sb = new StringBuilder(requestUrl);
            if (params != null && params.size() > 0) {
                sb.append("?");
                Set<String> keys = params.keySet();
                for (String key : keys) {
                    sb.append(URLEncoder.encode(key, "UTF-8"));
                    sb.append("=");
                    sb.append(URLEncoder.encode(params.get(key), "UTF-8"));
                    sb.append("&");
                }
            }

            // 打开连接
            url = new URL(sb.toString());
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod(HttpMethod.GET.name());

            // 处理请求头
            handleHeaders(conn, headers);

            return getResponse(conn);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * http POST 请求
     * @param requestUrl
     * @param params
     * @return
     */
    public static String httpPostSendRequestBody(String requestUrl, Map<String, Object> params) {
        return httpPostSendRequestBody(requestUrl, params, null);
    }

    /**
     * http POST 请求
     * @param requestUrl
     * @param params
     * @param headers
     * @return
     */
    public static String httpPostSendRequestBody(String requestUrl, Map<String, Object> params, Map<String, String> headers) {

        OutputStream outputStream = null;
        try {

            HttpURLConnection conn = (HttpURLConnection) (new URL(requestUrl).openConnection());
            conn.setRequestMethod(HttpMethod.POST.name());
            conn.setDoInput(true);
            conn.setDoOutput(true);
            conn.setUseCaches(false);
            // 处理请求头
            if (headers == null) {
                headers = new HashMap<>();
            }
            headers.put("Content-Type", "application/json");
            handleHeaders(conn, headers);

            if (params != null && params.size() > 0) {
                outputStream = conn.getOutputStream();
                outputStream.write(JSON.toJSONBytes(params));
                outputStream.flush();
            }

            return getResponse(conn);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            shutdownStream(outputStream);
        }

        return null;
    }

    /**
     * http POST 请求
     * @param requestUrl
     * @param params
     * @return
     */
    public static String httpPost(String requestUrl, Map<String, Object> params) {

        return httpPost(requestUrl, params, null);
    }

    /**
     * http POST 请求
     * @param requestUrl
     * @param params
     * @param headers
     * @return
     */
    public static String httpPost(String requestUrl, Map<String, Object> params, Map<String, String> headers) {

        OutputStream outputStream = null;
        try {

            HttpURLConnection conn = (HttpURLConnection) (new URL(requestUrl).openConnection());
            conn.setRequestMethod(HttpMethod.POST.name());
            conn.setDoInput(true);
            conn.setDoOutput(true);
            conn.setUseCaches(false);
            // 处理请求头
            if (headers == null) {
                headers = new HashMap<>();
            }
            headers.put("Content-Type", "application/json");
            handleHeaders(conn, headers);

            if (params != null && params.size() > 0) {
                outputStream = conn.getOutputStream();
                outputStream.write(JSON.toJSONBytes(params));
                outputStream.flush();
            }

            return getResponse(conn);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            shutdownStream(outputStream);
        }

        return null;
    }

    /**
     * 处理请求头
     * @param conn
     * @param headers
     */
    private static void handleHeaders(HttpURLConnection conn, Map<String, String> headers) {
        // 处理请求头
        if (headers != null && headers.size() > 0) {
            Set<String> keys = headers.keySet();
            for (String key : keys) {
                conn.setRequestProperty(key, headers.get(key));
            }
        }
    }

    /**
     * 获取响应字符串
     * @param conn
     * @return
     * @throws Exception
     */
    private static String getResponse(HttpURLConnection conn) {
        StringBuilder response = new StringBuilder();
        try (InputStream inputStream = conn.getInputStream()){
            // 封装响应
            BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
            String str;
            while ((str = br.readLine()) != null) {
                response.append(str);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return response.toString();
    }

    /**
     * 关闭流文件
     * @param stream
     */
    private static void shutdownStream(Closeable... stream) {
        if (stream != null && stream.length > 0) {
            for (Closeable closeable : stream) {
                if (closeable != null) {
                    try {
                        closeable.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

}
